﻿using System.Collections.Generic;
using System.IO;
using System;
using System.Xml;

using Ch.Admin.Bfs.Sms.Sdmx.Common;
using Ch.Admin.Bfs.Sms.Sdmx.Schemes;
using Ch.Admin.Bfs.Sms.Sdmx.IO.Xml;
using Ch.Admin.Bfs.Sms.Sdmx.Metadata;


using SdmxMl.Manager;
using SdmxMl.Structure;
using SdmxMl.Common;

namespace Ch.Admin.Bfs.Sms.Sdmx.Registry
{
    //public class TinyArtefactRegistry : AbstractArtefactRegistry
    //{
    //    #region Constants
    //    private const string TEST_AGENCY_IDENTIFIER = "TEST";
    //    private const string TEST_AGENCY_NAME_DEFAULT_TEXT = "Test Agency";
    //    #endregion

    //    #region Inner members
    //    private Agency agency;
    //    private SmManager sm;
    //    private Schemes.AgencyScheme scheme;
        
    //    private Dictionary<MaintainableArtefactReference, MaintainableArtefact> dicoMaintenable;
    //    #endregion

    //    #region Constructor
    //    public TinyArtefactRegistry()
    //    {
    //        InitRegistry();
    //    }

    //    private void InitRegistry()
    //    {
    //        sm = new SmManager();
    //        dicoMaintenable = new Dictionary<MaintainableArtefactReference, MaintainableArtefact>();

    //        scheme = new Schemes.AgencyScheme(Schemes.Agency.ROOT_AGENCY, VersionableArtefact.FIRST_VERSION);
    //        dicoMaintenable.Add((MaintainableArtefactReference)scheme.Reference, scheme);
    //        // SDMX agency
    //        agency = scheme.CreateAgency();
    //        agency.Identifier = "SDMX";
    //        agency.Name.DefaultText = "SDMX Agency";

    //        agency = scheme.CreateAgency();
    //        agency.Identifier = "ESTAT";
    //        agency.Name.DefaultText = "Eurostat";

    //        // Now create CH1 agencies
    //        OrganisationSchemesType orgNsi = SdmxMl.Msg.HeaderGenerator.NSI_OrgScheme;
    //        if (orgNsi != null)
    //        {
    //            foreach (OrganisationType o in orgNsi.Agencies)
    //            {
    //                agency = scheme.CreateAgency();
    //                agency.Identifier = o.Id;
    //                agency.Name.DefaultText = o.Name.GetForLanguage(LangSupport.ENGLISH_ID); ;

    //            }
    //        }

    //    }
    //    #endregion

    //    #region Clear the content of the registry
    //    public void Clear()
    //    {
    //        InitRegistry();
    //    }
    //    #endregion

    //    #region Get artefacts

    //    private SdmxArtefactType GetArType(MaintainableArtefactReference reference)
    //    {

    //        SdmxArtefactType arType = SdmxArtefactType.None;

    //        // Transcode type
    //        switch (reference.Type)
    //        {
    //            case ArtefactType.MetadataStructureDefinition:
    //                arType = SdmxArtefactType.MetadataStructureDefinitions;
    //                break;
    //            case ArtefactType.Codelist:
    //                arType = SdmxArtefactType.CodeLists;
    //                break;
    //            case ArtefactType.DataStructureDefinition:
    //                arType = SdmxArtefactType.KeyFamilies;
    //                break;
    //            case ArtefactType.ConceptScheme:
    //                arType = SdmxArtefactType.Concepts;
    //                break;
    //            case ArtefactType.HierarchicalCodelist:
    //                arType = SdmxArtefactType.HierarchicalCodelists;
    //                break;
    //            case ArtefactType.CategoryScheme:
    //                arType = SdmxArtefactType.CategorySchemes;
    //                break;
    //            case ArtefactType.StructureSet:
    //                arType = SdmxArtefactType.StructureSets;
    //                break;
    //            case ArtefactType.Process:
    //                arType = SdmxArtefactType.Processes;
    //                break;

    //            default:
    //                arType = SdmxArtefactType.None;
    //                break;
    //        }
    //        return arType;
    //    }

    //    private SdmxMessage GetArtefactAsMessage(ArtefactRefTyped art)
    //    {
    //        SdmxMessage msg = null;
    //        try
    //        {
    //            sm.GetArtefact(art.Type, art, true);

    //            XmlDocument xmlDoc = sm.GetArtefactAsDocument(art.Type, art); ;
    //            MemoryStream xmlStream = new MemoryStream();
    //            xmlDoc.Save(xmlStream);
    //            xmlStream.Flush();
    //            xmlStream.Position = 0;

    //            msg = SdmxXmlUtil.ReadMessage(xmlStream);
    //        }
    //        catch (Exception ex)
    //        {
    //            throw new RegistryException("Unable to fetch " + art.FullIdent, ex);
    //        }
    //        return msg;
    //    }

    //    /// <summary> Return the maintainable artefact corresponding to the specified reference </summary>
    //    /// <param name="reference"> The reference to an artefact to be retrieved </param>
    //    /// <returns> The maintainable artefact corresponding to the specified reference </returns>
    //    public override MaintainableArtefact Get(MaintainableArtefactReference reference)
    //    {
    //        List<Agency> agencyList = new List<Agency>(scheme.Agencies);
    //        Agency agency = agencyList.Find(x => (x.Identifier == reference.AgencyIdentifier));
    //        if (agencyList == null)
    //        {
    //            agency = scheme.CreateAgency();
    //            agency.Identifier = reference.Identifier;
    //            agency.Name.DefaultText = "fly creation";
    //        }

    //        // Already in cache ?
    //        if (dicoMaintenable.ContainsKey(reference))
    //            return dicoMaintenable[reference];

            
    //        MaintainableArtefact result = null;
    //        SdmxArtefactType arType = GetArType(reference);

    //        try
    //        {
    //            ArtefactRefTyped art = new ArtefactRefTyped(arType, reference.FullIdentifier);
    //            StructureMessage msg = GetArtefactAsMessage(art) as StructureMessage;

    //            result = msg.Artefacts[0];
    //        }
    //        catch (Exception ex)
    //        {
    //            throw new RegistryException("Unable to fetch " + reference.FullIdentifier, ex);
    //        }

    //        if (result != null)
    //            dicoMaintenable.Add(reference, result);

    //        return result;
    //    }

    //    /// <summary> Return the maintainable artefact corresponding to the specified reference </summary>
    //    /// <param name="reference"> The reference to an artefact to be retrieved </param>
    //    /// <returns> The maintainable artefact corresponding to the specified reference </returns>
    //    public MetadataSet GetMetaSet(string fullId)
    //    {
    //        MetadataSet mset = null;
    //        try
    //        {
    //            ArtefactRefTyped art = new ArtefactRefTyped(SdmxArtefactType.MetadataSet, fullId);
    //            MetadataMessage msg = GetArtefactAsMessage(art) as MetadataMessage;

    //            mset = msg.MetadataSets[0];
    //        }
    //        catch (Exception ex)
    //        {
    //            throw new RegistryException("Unable to fetch " + fullId, ex);
    //        }

    //        return mset;

    //    }




    //    /// <summary> Return a stream containing the maintainable artefact corresponding to the specified reference </summary>
    //    /// <param name="reference"> The reference to an artefact to be retrieved </param>
    //    /// <returns> The stream containing the maintainable artefact corresponding to the specified reference </returns>
    //    public override Stream GetAsStream(MaintainableArtefactReference reference)
    //    {
    //        MemoryStream result = new MemoryStream();
    //        //         SdmxXmlUtil.Write(new StructureMessage(this.agency, Get(reference)), result);

    //        return result;
    //    }
    //    #endregion
    //    #region Search artefacts
    //    /// <summary> Check that the specified artefact exists in the registry </summary>
    //    /// <param name="reference"> The reference to an artefact </param>
    //    /// <returns> True if and only if the specified artefact exists in the registry </returns>
    //    public override bool Exist(MaintainableArtefactReference reference)
    //    {
    //        return false; // artefacts.ContainsKey(reference);
    //    }
    //    #endregion

    //    #region Update artefacts
    //    /// <summary> Delete the artefact corresponding to the specified reference </summary>
    //    /// <param name="reference"> The artefact to be removed </param>
    //    public override void Delete(MaintainableArtefactReference reference)
    //    {
    //        //if (!artefacts.Remove(reference))
    //        //{
    //        //    throw new RegistryException("Could not delete the artefact '" + reference.ToString() + "': the artefact does not exist!");
    //        //}
    //    }

    //    /// <summary> Update the specified artefact. </summary>
    //    /// <param name="artefact"> The artefact to be updated </param>
    //    public override void Update(MaintainableArtefact artefact)
    //    {
    //     //   artefacts[artefact.Reference as MaintainableArtefactReference] = artefact;
    //    }

    //    /// <summary> Partially update the specified artefact. 
    //    ///           The partial backup means that only descriptions and names are modified upon the update </summary>
    //    /// <param name="artefact"> The artefact to be updated </param>
    //    public override void PartialUpdate(MaintainableArtefact artefact)
    //    {
    //        //if (!artefacts.ContainsKey(artefact.Reference as MaintainableArtefactReference))
    //        //{
    //        //    throw new RegistryException("Cannot partially update the artefact '" + artefact.Reference.ToString() +
    //        //                                "': the registry does not contains yet the artefact.");
    //        //}
    //        //if (!artefacts[artefact.Reference as MaintainableArtefactReference].Compare(artefact, false, true, true, false, true))
    //        //{
    //        //    throw new RegistryException("Cannot partially update the artefact '" + artefact.Reference.ToString() +
    //        //                                "': the update contains forbidden modifications !");
    //        //}
    //        //artefacts[artefact.Reference as MaintainableArtefactReference] = artefact;
    //    }
    //    #endregion
    //}
}
